package com.frame.shiro;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.DefaultPasswordService;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.frame.domain.Permission;
import com.frame.domain.Role;
import com.frame.domain.User;
import com.frame.service.PermissionService;
import com.frame.service.RoleService;
import com.frame.service.UserService;
import com.frame.utils.MD5Util;

/**
 * Shiro authentication & authorization realm that relies on OrientDB as
 * datastore.
 */
@Component
public class AdminRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    
    @Autowired
    private RoleService roleService;
    
    @Autowired
    private PermissionService permissionService;
    
    @Autowired
    DefaultPasswordService passwordService;

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token)throws AuthenticationException {
        final UsernamePasswordToken credentials = (UsernamePasswordToken) token;
        final String email = credentials.getUsername();
        final char[] password = credentials.getPassword();
        if (email == null) {
            throw new UnknownAccountException("Email not provided");
        }
        final User user = userService.findByEmailAndActive(email, true);
        if (user == null) {
            throw new UnknownAccountException("Account does not exist");
        }
        if(password==null || !MD5Util.getMD5Code(String.valueOf(password)).equals(user.getPassword())){
        	throw new UnknownAccountException("Password is incorrect");
        };
        AuthenticationInfo info = new SimpleAuthenticationInfo(email,password, passwordService.hashPassword(password), getName());
        return info;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            final PrincipalCollection principals) {
        // retrieve role names and permission keys
        final String email = (String) principals.getPrimaryPrincipal();
        final User user = userService.findByEmailAndActive(email, true);
        if (user == null) {
            throw new UnknownAccountException("Account does not exist");
        }
        List<Role> roles = roleService.findByUserid(user.getId());
        final int size = roles.size();
        final Set<String> rolekeys = new LinkedHashSet<>(size);
        final Set<String> permkeys = new LinkedHashSet<>();
        if (size > 0) {
            for (Role role : roles) {
            	rolekeys.add(role.getRolekey());
            	List<Permission> permissions = permissionService.findByRoleid(role.getId());
                for (Permission permission : permissions) {
                    permkeys.add(permission.getPermkey());
                }
            }
        }
        final SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(rolekeys);
        info.setStringPermissions(permkeys);
        return info;
    }
}
